package services

import (
	"GOPAAS/configs/config"
	"GOPAAS/internal/app/global"
	"GOPAAS/internal/app/model"
	"GOPAAS/internal/utils"
	"fmt"
	"gorm.io/gorm"
	"strconv"
	"strings"
	"time"
)

type Area struct {
	Id   int64  `json:"id"`
	Name string `json:"name"`
}
type CodeOption struct {
	Code string `json:"code"`
	Name string `json:"name"`
}
type ModelOption struct {
	Id    int64  `json:"id"`
	Model string `json:"model"`
	Name  string `json:"name"`
}
type TitleItem struct {
	Id       int64  `json:"id"`
	Name     string `json:"name"`
	Shortcut string `json:"shortcut"`
}

// ResourceCalendar 工作时间
type ResourceCalendar struct {
	Id          int64   `json:"id"`
	Name        string  `json:"name"`
	HoursPerDay float64 `json:"hours_per_day"`
}

func GetProvince(country_id int64) ([]Area, error) {
	db = getDB()
	var res []Area
	result := db.Model(&model.ResCountryState{}).Where("country_id=?", country_id).Find(&res)
	return res, result.Error
}
func GetModel() ([]ModelOption, error) {
	db = getDB()
	var res []ModelOption
	result := db.Model(&model.IrModel{}).Find(&res)
	return res, result.Error
}

func GetLang() ([]CodeOption, error) {
	db = getDB()
	var res []CodeOption
	result := db.Model(&model.ResLang{}).Where("active=?", true).Find(&res)
	return res, result.Error
}
func GetTimeZone() []CodeOption {
	db = getDB()
	var res []CodeOption
	for _, v := range global.TimeZone {
		res = append(res, CodeOption{
			v,
			v,
		})
	}
	return res
}

// GetAllGroups 获取所有分组
func GetAllGroups() map[string][]Area {
	db = getDB()
	var groups []model.ResGroups
	var res = make(map[string][]Area, 0)
	db.Preload("Category").Select("id,name,category_id").Order("category_id,id").Find(&groups)
	for _, v := range groups {
		category_name := v.Category.Name
		_, exist := res[category_name]
		if !exist {
			res[category_name] = []Area{{Id: v.Id, Name: v.Name}}
		} else {
			res[category_name] = append(res[category_name], Area{Id: v.Id, Name: v.Name})
		}
	}
	return res
}
func GetCategory() ([]global.TreeItem, error) {
	db = getDB()
	var res []global.TreeItem
	result := db.Model(&model.IrModuleCategory{}).Where("visible=?", true).Order("parent_id,id").Find(&res)
	return res, result.Error
}
func GetCategory2() ([]global.TreeItem2, error) {
	db = getDB()
	var res []global.TreeItem2
	result := db.Model(&model.IrModuleCategory{}).Where("visible=?", true).Select("id", "name", "parent_id", "'true' as open").Order("parent_id,id").Find(&res)
	return res, result.Error
}
func GetCmsCategory() ([]global.TreeItem, error) {
	db = getDB()
	var res []global.TreeItem
	result := db.Model(&model.CmsCategory{}).Where("active=?", true).Order("parent_id,id").Find(&res)
	return res, result.Error
}
func GetCmsCategory2() ([]global.TreeItem2, error) {
	db = getDB()
	var res []global.TreeItem2
	result := db.Model(&model.CmsCategory{}).Where("active=?", true).Select("id", "name", "parent_id", "'true' as open").Order("parent_id,id").Find(&res)
	return res, result.Error
}
func GetCity(state_id int64, lang string) ([]Area, error) {
	db = getDB()
	var res []Area
	result := db.Model(&model.ResCity{}).Where("state_id=?", state_id).Find(&res)
	for k, v := range res {
		res[k].Name = utils.GetJsonName(v.Name, lang)
	}
	return res, result.Error
}
func GetArea(city_id int64) ([]Area, error) {
	db = getDB()
	var res []Area
	result := db.Model(&model.ResArea{}).Where("city_id=?", city_id).Find(&res)
	//for k, v := range res {
	//	res[k].Name = utils.GetJsonName(v.Name,lang)
	//}
	return res, result.Error
}
func GetCountry(lang string) ([]Area, error) {
	db = getDB()
	var res []Area
	result := db.Model(&model.ResCountry{}).Find(&res)
	for k, v := range res {
		res[k].Name = utils.GetJsonName(v.Name, lang)
	}
	return res, result.Error
}

type HrLeaveTypeOption struct {
	Area
	RequestUnit string  `json:"request_unit"`
	Num         float64 `json:"num"`
	IsLimit     bool    `json:"is_limit"`
}

// GetLeaveTypes 获取请加类型
func GetLeaveTypes(lang string) ([]HrLeaveTypeOption, error) {
	db = getDB()
	var res []HrLeaveTypeOption
	var data []model.HrLeaveType
	result := db.Where("active=?", true).Find(&data)
	for _, v := range data {
		res = append(res, HrLeaveTypeOption{
			Area: Area{
				Id:   v.Id,
				Name: utils.GetJsonName(v.Name, lang),
			},
			RequestUnit: v.RequestUnit,
		})
	}
	return res, result.Error
}
func GetTitle() ([]TitleItem, error) {
	db = getDB()
	var res []TitleItem
	result := db.Model(&model.ResPartnerTitle{}).Find(&res)
	return res, result.Error
}
func GetProjectTags() ([]Area, error) {
	db = getDB()
	var res []Area
	result := db.Model(&model.ProjectTags{}).Find(&res)
	return res, result.Error
}

func GetWorkingTime(company_id int64) ([]ResourceCalendar, error) {
	db = getDB()
	var res []ResourceCalendar
	result := db.Model(&model.ResourceCalendar{}).Where("company_id=? and active=?", company_id, true).Select("id", "name", "hours_per_day").Order("id").Find(&res)
	return res, result.Error
}

func GetHrJob(company_id int64, lang string) ([]Area, error) {
	db = getDB()
	var res []Area
	result := db.Model(&model.HrJob{}).Where("company_id", company_id).Select("id", "name").Order("id").Find(&res)
	for k, v := range res {
		res[k].Name = utils.GetJsonName(v.Name, lang)
	}
	return res, result.Error
}

// GetUsersCount 获取个人用户注册量
func GetUsersCount() int64 {
	db = getDB()
	var user model.ResUsers
	var count int64
	db.Model(&user).Joins("join res_partner on res_users.partner_id=res_partner.id and res_partner.active=true").Where("res_users.active=?", true).Count(&count)
	return count
}

// GetCompanyCount 获取企业用户注册量
func GetCompanyCount() int64 {
	db = getDB()
	var num int64
	db.Model(&model.ResCompany{}).Joins("join res_partner on res_company.partner_id=res_partner.id and res_partner.active=true").Where("res_company.id>?", 0).Count(&num)
	return num
}

// GetProductCount 获取应用上架量
func GetProductCount() int64 {
	db = getDB()
	var num int64
	db.Model(&model.ProductProduct{}).Joins("join product_template on product_product.product_tmpl_id=product_template.id").Where("product_product.active=? and product_product.app_download=? and product_template.sale_ok=? and product_template.is_published=?", true, true, true, true).Count(&num)
	return num
}

// GetIndustryList 获取行业下拉
func GetIndustryList() ([]Area, error) {
	db = getDB()
	var res []Area
	result := db.Model(&model.UtmIndustry{}).Where("active=?", true).Find(&res)
	return res, result.Error
}

// GetHelpdeskStageList 获取状态列表
func GetHelpdeskStageList() ([]Area, error) {
	db = getDB()
	var res []Area
	result := db.Model(&model.HelpdeskStage{}).Where("active=?", true).Order("sequence").Find(&res)
	return res, result.Error
}

// GetHelpdeskTypeList 获取类型列表
func GetHelpdeskTypeList(lang string) ([]Area, error) {
	db = getDB()
	var res []Area
	result := db.Model(&model.HelpdeskTicketType{}).Order("sequence").Find(&res)
	for k, v := range res {
		res[k].Name = utils.GetJsonName(v.Name, lang)
	}
	return res, result.Error
}

// IsGroupUser 判断是否具有某个权限
func IsGroupUser(perm string, user_id int64) bool {
	db = getDB()
	var model_data model.IrModelData
	db.Where("name=?", perm).First(&model_data)
	if model_data.Id > 0 {
		var group_user model.ResGroupsUsersRel
		res := db.Where("gid=? and uid=?", model_data.ResId, user_id).First(&group_user)
		if res.RowsAffected > 0 {
			return true
		}
	}
	return false
}

// CategoryTree 分类树
func CategoryTree() (result []global.Tree) {
	category_list, _ := GetCategory()
	tree(&category_list, 0, &result)
	return
}

// CmsCategoryTree 分类树
func CmsCategoryTree() (result []global.Tree) {
	category_list, _ := GetCmsCategory()
	tree(&category_list, 0, &result)
	return
}
func tree(list *[]global.TreeItem, pid int64, result *[]global.Tree) {
	for _, v := range *list {
		if v.ParentId.Int64 == pid {
			var item global.Tree
			item.Id = v.Id
			item.Name = v.Name
			item.ParentId = v.ParentId
			tree(list, v.Id, &item.Children)
			*result = append(*result, item)
		}
	}
	return
}
func GetImage(size int64, model string, res_id int64) string {
	attach, _ := GetAttachService(0).GetAttach(model, res_id, "image_"+strconv.Itoa(int(size)))
	return fmt.Sprintf("http://"+config.Conf.Host+"/web/image/%d?field=%s&model=%s&id=%d&t=%s", size, "", model, res_id, attach.Checksum)
}
func GetSimpleImage(model string, res_id int64, field string) string {
	attach, _ := GetAttachService(0).GetAttach(model, res_id, field)
	return fmt.Sprintf("http://"+config.Conf.Host+"/web/image/%d?field=%s&model=%s&id=%d&t=%s", 0, field, model, res_id, attach.Checksum)
}
func GetAttach(model string, res_id int64, check_sum string) string {
	return fmt.Sprintf("http://"+config.Conf.Host+"/web/file/%s?&model=%s&id=%d", check_sum, model, res_id)
}

func GetSelectOption(lang string, model_name string) map[string][]CodeOption {
	db = getDB()
	var fields []model.IrModelFields
	var result = make(map[string][]CodeOption, 0)
	db.Where("model=? and ttype=?", model_name, "selection").Find(&fields)
	for _, v := range fields {
		var list []CodeOption
		var selects []model.IrModelFieldsSelection
		db.Where("field_id=?", v.Id).Find(&selects)
		for _, vv := range selects {
			list = append(list, CodeOption{
				vv.Value,
				utils.GetJsonName(vv.Name, lang),
			})
		}
		result[v.Name] = list
	}
	return result
}
func GetMapName(model_name string, field string, key string, lang string) string {
	dict := GetSelectOption(lang, model_name)
	for _, v := range dict[field] {
		if v.Code == key {
			return v.Name
		}
	}
	return ""
}

type RoomsUse struct {
	Id    int64  `json:"id"`
	Name  string `json:"name"`
	Max   int    `json:"max"`
	IsUse bool   `json:"is_use"`
}

// GetRooms 获取会议室列表
func GetRooms(start_time string, end_time string, allday bool) (res []RoomsUse) {
	var rooms []RoomsUse
	var calendar_rooms []model.CalendarRoom
	var q *gorm.DB
	if allday {
		q = db.Where("start_date between ? and ?", start_time, end_time).Or("stop_date between ? and ?", start_time, end_time)
	} else {
		q = db.Where("start between ? and ?", start_time, end_time).Or("stop between ? and ?", start_time, end_time)
	}
	db.Where("state=?", "已审核").Select("Id", "Name", "Max").Find(&calendar_rooms)
	for _, v := range calendar_rooms {
		var calendar model.CalendarEvent
		db.Model(&calendar).Where("state=? and room_id=?", "待办", v.Id).Where(q).First(&calendar)
		rooms = append(rooms, RoomsUse{
			Id:    v.Id,
			Name:  v.Name,
			Max:   v.Max,
			IsUse: calendar.Id > 0,
		})
	}
	return rooms
}

var DTcloudConfig = make(map[string]string, 0)

// GetDTcloudConfig 获取后台配置
func GetDTcloudConfig(key string) string {
	value, e := DTcloudConfig[key]
	if e {
		return value
	}
	db = getDB()
	var conf model.IrConfigParameter
	db.Where("key=?", key).First(&conf)
	if conf.Id > 0 {
		DTcloudConfig[key] = conf.Value
		return conf.Value
	}
	return ""
}

// GetUploaderPath 获取上传文件地址
func GetUploaderPath(model_name string, res_id int64, field string, folder_id int64, login_user_id int64, company_id int64) string {
	var uploader_path = config.Conf.UploaderPath + "/index?res_model=%s&res_id=%d&res_field=%s&company_id=%d&create_uid=%d&write_uid=%d&access_token=%s&folder_id=%d&name=file&offset=10"
	var token model.DtcloudToken
	db.Where("name=? and user_id=? and company_id=?", "GO_Upload", login_user_id, company_id).First(&token)
	if token.Id == 0 {
		user_service := GetUserService(login_user_id)
		token, _ = user_service.CreateToken("GO_Upload")
	}
	if time.Now().After(token.TokenDate) {
		token.TokenDate = time.Now().AddDate(0, 0, 1)
		db.Select("TokenDate").Save(&token)
	}
	return fmt.Sprintf(uploader_path, model_name, res_id, field, company_id, login_user_id, login_user_id, token.AccessToken, folder_id)
}

type ModelFields struct {
	Model string
	Name  string
}

// GetModelFields 获取模型字段数据
func GetModelFields(model_name string, fields []string, ids []int64) (data []map[string]interface{}) {
	db = getDB()
	var result []ModelFields
	fields = append(fields, "active")
	if len(ids) > 0 {
		fields = append(fields, "id")
	}
	db.Model(&model.IrModelFields{}).Where("model=? and name in ?", model_name, fields).Find(&result)
	data = make([]map[string]interface{}, 0)
	table_name := utils.GetTableNameByModel(model_name)
	var filter_fields = make([]string, 0)
	var select_raw string
	var query = "SELECT %s FROM %s where true"
	var has_id bool
	for _, v := range result {
		if v.Name == "id" && len(ids) > 0 {
			query += " and id in ?"
			has_id = true
		}
		if v.Name == "active" {
			query += " and active=true"
			continue
		}
		filter_fields = append(filter_fields, v.Name)
	}
	select_raw = strings.Join(filter_fields, ",")
	query = fmt.Sprintf(query, select_raw, table_name)
	if has_id {
		db.Raw(query, ids).Scan(&data)
	} else {
		db.Raw(query).Scan(&data)
	}
	//res = make(map[string][]interface{}, 0)
	////转化数据
	//for _, vv := range data {
	//	for _, f := range fields {
	//		if d, e := vv[f]; e {
	//			if _, ee := res[f]; ee {
	//				res[f] = append(res[f], d)
	//			} else {
	//				res[f] = []interface{}{d}
	//			}
	//		}
	//	}
	//}
	return
}

// GetProductBrandList 获取产品品牌下拉
func GetProductBrandList() ([]Area, error) {
	db = getDB()
	var res []Area
	result := db.Model(&model.ProductBrand{}).Where("active=?", true).Find(&res)
	return res, result.Error
}

// GetUomList 获取单位下拉
func GetUomList(lang string) ([]Area, error) {
	db = getDB()
	var res []Area
	result := db.Model(&model.UomUom{}).Where("active=?", true).Find(&res)
	for k, v := range res {
		res[k].Name = utils.GetJsonName(v.Name, lang)
	}
	return res, result.Error
}

// GetProductAttributes 获取产品属性
func GetProductAttributes(lang string) ([]Area, error) {
	db = getDB()
	var res []Area
	result := db.Model(&model.ProductAttribute{}).Find(&res)
	for k, v := range res {
		res[k].Name = utils.GetJsonName(v.Name, lang)
	}
	return res, result.Error
}

// GetProductAttributeValues 获取产品属性值
func GetProductAttributeValues(attribute_id int64, lang string) ([]Area, error) {
	db = getDB()
	var res []Area
	result := db.Model(&model.ProductAttributeValue{}).Where("attribute_id=?", attribute_id).Order("sequence").Find(&res)
	for k, v := range res {
		res[k].Name = utils.GetJsonName(v.Name, lang)
	}
	return res, result.Error
}

// GetProductAttributeValuePrice 获取产品属性值价格
func GetProductAttributeValuePrice(product_tmpl_id int64, attr_id int64, value_id int64) float64 {
	var info model.ProductTemplateAttributeValue
	db = getDB()
	db.Where("product_tmpl_id=? and attribute_id=? and product_attribute_value_id=?", product_tmpl_id, attr_id, value_id).First(&info)
	return info.PriceExtra
}
